﻿using Mapster;
using Orleans.EventSourcing;
using Orleans.Providers;
using Orleans.Streams;

namespace orleans_demo.Services
{
    [StorageProvider(ProviderName = "SnapshotStore")]
    public class UserGrain : JournaledGrain<UserState, UserEvent>, IUserGrain
    {
       // private IUserIndexGrain _index;
        private IAsyncStream<UserEvent> _stream;

        public override async Task OnActivateAsync(CancellationToken cancellationToken)
        {
            // _index = GrainFactory.GetGrain<IUserIndexGrain>("0"); // 使用固定Key的索引Grain
            var streamProvider = this.GetStreamProvider("UserStream");
            _stream = streamProvider.GetStream<UserEvent>("0", "ALL_USERS");
            // CancellationTokenSource cts = new CancellationTokenSource();
            await base.OnActivateAsync(cancellationToken);
        }

        public Task Create(UserDto user)
        {
            if (user == null) throw new ArgumentNullException(nameof(user));
            // 生成事件
            var userInfo = new UserCreatedEvent
            {
                Id = this.GetPrimaryKeyString(),
                Name = user.Name,
                Email = user.Email,
                Timestamp = DateTime.UtcNow
            };
            RaiseEvent(userInfo);
            //_index.AddUser(userInfo.Adapt<UserInfo>()); // 添加到索引

             _stream.OnNextAsync(userInfo);
            return ConfirmEvents();
        }

        public Task Update(UserDto user)
        {
            if (State.IsDeleted)
                throw new InvalidOperationException("Cannot update deleted user");

            RaiseEvent(new UserUpdatedEvent
            {
                Name = user.Name,
                Email = user.Email,
                Timestamp = DateTime.UtcNow
            });

            return ConfirmEvents();
        }

        public Task Delete()
        {
            RaiseEvent(new UserDeletedEvent { Timestamp = DateTime.UtcNow });
            //_index.RemoveUser(this.GetPrimaryKeyString()); // 从索引移除
            return ConfirmEvents();
        }

        public Task<UserDto> Get()
        {
            if (State.IsDeleted)
                return Task.FromResult<UserDto>(null);

            return Task.FromResult(new UserDto
            {
                Name = State.Name,
                Email = State.Email,
                CreatedAt = State.CreatedAt
            });
        }

        // 事件应用逻辑
        protected override void TransitionState(UserState state, UserEvent @event)
        {
            switch (@event)
            {
                case UserCreatedEvent created:
                    state.Id = created.Id;//this.GetPrimaryKeyString();
                    state.Name = created.Name;
                    state.Email = created.Email;
                    state.CreatedAt = created.Timestamp;
                    state.IsDeleted = false;
                    break;

                case UserUpdatedEvent updated:
                    state.Name = updated.Name;
                    state.Email = updated.Email;
                    break;

                case UserDeletedEvent _:
                    state.IsDeleted = true;
                    break;
            }
        }
    }
}
